package com.gwtsz.chart.highlight;

import android.util.Log;
import com.gwtsz.chart.components.YAxis;
import com.gwtsz.chart.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider;
import com.gwtsz.chart.interfaces.datasets.IDataSet;
import com.gwtsz.chart.output.customer.MyCombinedChart;
import com.gwtsz.chart.output.customer.MyLineChart;
import com.gwtsz.chart.utils.SelectionDetail;
import com.gwtsz.chart.utils.Utils;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Philipp Jahoda on 21/07/15.
 */
public class ChartHighlighter<T extends BarLineScatterCandleBubbleDataProvider> {

	/** instance of the data-provider */
	protected T mChart;

	public ChartHighlighter(T chart) {
		this.mChart = chart;
	}

	/**
	 * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels.
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public Highlight getHighlight(float x, float y) {

		int xIndex = getXIndex(x);

		SelectionDetail selectionDetail = getSelectionDetail(xIndex, y, -1);
		float minFloat=0;
		float maxFloat=0;
		if(mChart instanceof MyLineChart){
			minFloat = ((MyLineChart) mChart).getAxisLeft().getAxisMinimum();
			maxFloat=((MyLineChart) mChart).getAxisLeft().getAxisMaximum();
		}else if(mChart instanceof MyCombinedChart){
			minFloat = ((MyCombinedChart) mChart).getAxisLeft().getAxisMinimum();
			maxFloat=((MyCombinedChart) mChart).getAxisLeft().getAxisMaximum();
		}

		/**
		 * 超出值范围处理展示为最后一根数据
		 */
		if (selectionDetail == null) {
			if (mChart instanceof MyLineChart) {
				int Index = xIndex;
				float yIndex = y;
				if (x < 0) {
					Index = 0;
				} else if (xIndex >= mChart.getData().getDataSetByIndex(0).getEntryCount() - 1) {
					Index = mChart.getData().getDataSetByIndex(0).getEntryCount() - 1;
				}
				if (getYIndex(y) >= maxFloat) {
					yIndex = maxFloat;
					return new Highlight(Index, yIndex, 0, 0);
				} else if (getYIndex(y) <= minFloat) {
					yIndex = minFloat;
					return new Highlight(Index, yIndex, 0, 0);
				}

				return new Highlight(Index, getYIndex(yIndex), 0, 0);
			}

			if(mChart instanceof MyCombinedChart){
				int maxIndex = mChart.getHighestVisibleXIndex();
				int minIndex=mChart.getLowestVisibleXIndex();
				Log.e("spenceAndroid","max:"+maxIndex);
				Log.e("spenceAndroid","min:"+minIndex);
				Log.e("spenceAndroid","Index:"+xIndex);
				int Index=0;
				float yIndex = y;
				if (x < minIndex) {
					Index = minIndex;
				} else if (xIndex >= maxIndex) {
					Index = maxIndex;
				}else {
					Index=xIndex;
				}

				if (getYIndex(y) >= maxFloat) {
					yIndex = maxFloat;
					return new Highlight(Index, yIndex, 0, 0);
				} else if (getYIndex(y) <= minFloat) {
					yIndex = minFloat;
					return new Highlight(Index, yIndex, 0, 0);
				}
				return new Highlight(Index, getYIndex(yIndex), 0, 0);
			}

			if (getYIndex(y) >= maxFloat) {
				return new Highlight(xIndex, maxFloat, 0, 0);
			} else if (getYIndex(y) <= minFloat) {
				return new Highlight(xIndex, minFloat, 0, 0);
			}
		}

		if(mChart instanceof MyCombinedChart){
			int maxIndex = mChart.getHighestVisibleXIndex();
			int minIndex=mChart.getLowestVisibleXIndex();
			Log.e("spenceAndroid","max:"+maxIndex);
			Log.e("spenceAndroid","min:"+minIndex);
			Log.e("spenceAndroid","Index:"+xIndex);
			int Index=xIndex;
			float yIndex = y;
			if (xIndex < minIndex) {
				Index = minIndex;
			} else if (xIndex >= maxIndex) {
				Index = maxIndex;
			}
			if (getYIndex(y) >= maxFloat) {
				yIndex = maxFloat;
				return new Highlight(Index, yIndex, selectionDetail.dataIndex, selectionDetail.dataSetIndex);
			} else if (getYIndex(y) <= minFloat) {
				yIndex = minFloat;
				return new Highlight(Index, yIndex, selectionDetail.dataIndex, selectionDetail.dataSetIndex);
			}

			return new Highlight(Index, getYIndex(yIndex), selectionDetail.dataIndex, selectionDetail.dataSetIndex);
		}


		if(getYIndex(y)>=maxFloat){
			return new Highlight(xIndex,
					maxFloat,
					0,
					0);
		}else if(getYIndex(y)<=minFloat){
			return new Highlight(xIndex,
					minFloat,
					0,
					0);
		}
/*
		return new Highlight(xIndex,
				selectionDetail.value,
				selectionDetail.dataIndex,
				selectionDetail.dataSetIndex);*/
        /**
		 spence customer
         **/
		return new Highlight(xIndex,
				getYIndex(y),
				selectionDetail.dataIndex,
				selectionDetail.dataSetIndex);
	}

	/**
	 * Returns the corresponding x-index for a given touch-position in pixels.
	 * 
	 * @param x
	 * @return
	 */
	protected int getXIndex(float x) {

		// create an array of the touch-point
		float[] pts = new float[2];
		pts[0] = x;

		// take any transformer to determine the x-axis value
		mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts);

		return Math.round(pts[0]);
	}

	/**
	 * spence customer
	 */
	protected float getYIndex(float y) {

		// create an array of the touch-point
		float[] pts = new float[2];
		pts[1] = y;

		// take any transformer to determine the x-axis value
		mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts);

		return pts[1];
	}

	/**
	 * Returns the corresponding SelectionDetail for a given xIndex and y-touch position in pixels.
	 * 
	 * @param xIndex
	 * @param y
	 * @param dataSetIndex
	 * @return
	 */
	protected SelectionDetail getSelectionDetail(int xIndex, float y, int dataSetIndex) {

		List<SelectionDetail> valsAtIndex = getSelectionDetailsAtIndex(xIndex, dataSetIndex);

		float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT);
		float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT);

		YAxis.AxisDependency axis = leftdist < rightdist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT;

		return Utils.getClosestSelectionDetailByPixelY(valsAtIndex, y, axis);
	}

	/**
	 * Returns a list of SelectionDetail object corresponding to the given xIndex.
	 *
	 * @param xIndex
	 * @param dataSetIndex dataSet index to look at. -1 if unspecified.
	 * @return
	 */
	protected List<SelectionDetail> getSelectionDetailsAtIndex(int xIndex, int dataSetIndex) {

		List<SelectionDetail> vals = new ArrayList<>();

		if (mChart.getData() == null) 
			return vals;

		float[] pts = new float[2];

		for (int i = 0, dataSetCount = mChart.getData().getDataSetCount();
			 i < dataSetCount;
			 i++) {

			if (dataSetIndex > -1 && dataSetIndex != i)
				continue;

			IDataSet dataSet = mChart.getData().getDataSetByIndex(i);

			// dont include datasets that cannot be highlighted
			if (!dataSet.isHighlightEnabled())
				continue;

			// extract all y-values from all DataSets at the given x-index
			final float[] yVals = dataSet.getYValsForXIndex(xIndex);
			for (float yVal : yVals) {
				if (Float.isNaN(yVal))
					continue;

				pts[1] = yVal;

				mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts);

				if (!Float.isNaN(pts[1]))
				{
					vals.add(new SelectionDetail(pts[1], yVal, i, dataSet));
				}
			}
		}

		return vals;
	}
}
